package com.duoqin.payservice.ui;

import android.animation.Animator;
import android.animation.AnimatorListenerAdapter;
import android.annotation.SuppressLint;
import android.app.Activity;
import android.arch.lifecycle.Observer;
import android.arch.lifecycle.ViewModelProviders;
import android.content.Intent;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import android.support.annotation.Nullable;
import android.support.v7.widget.ListPopupWindow;
import android.text.TextUtils;
import android.util.Log;
import android.view.Gravity;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.AdapterView;
import android.widget.BaseAdapter;
import android.widget.ImageView;
import android.widget.PopupWindow;
import android.widget.TextView;
import android.widget.Toast;

import com.duoqin.account.DuoqinAccount;
import com.duoqin.common.data.DefaultResponse;
import com.duoqin.common.data.QRCodeResponse;
import com.duoqin.common.ui.AbsActivity;
import com.duoqin.common.viewmodel.AppViewModel;
import com.duoqin.common.viewmodel.BaseViewModel;
import com.duoqin.payservice.Pay;
import com.duoqin.payservice.data.RechargeRequest;
import com.duoqin.payservice.data.RechargeResponse;
import com.duoqin.payservice.viewmodel.PayViewModel;
import com.duoqin.syncassistant.R;

import java.util.ArrayList;
import java.util.List;
import java.util.Random;


public class PayActivity extends AbsActivity {
    public static final String INTENT_EXTRA_COMMODITY_ID = "commodityId";
    public static final String INTENT_EXTRA_PAY_TYPE = "payType";
    public static final String INTENT_EXTRA_CHARGE_AMMOUNT = "chargeAmount";
    public static final String INTENT_EXTRA_DEPOSITEPLANS = "depositPlans";
    public static final String INTENT_EXTRA_PRICE = "price";

    private static final ArrayList<String> mPayMethod = new ArrayList<>();
    private static final ArrayList<Integer> mPayMethodRes = new ArrayList<>();

    private AppViewModel mAppViewModel;
    private PayViewModel mPayViewModel;

    private ImageView mPayQRIV;
    private TextView mPayNoticeTV;
    private View mProgressView;
    private ListPopupWindow mListPopupWindow;

    private int mCommodityId;
    private String mPayType;
    private double mChargeAmmount;
    private int mDepositePlans;
    private List<Integer> mPriceList;

    private String mTradeNumber;
    private Bitmap mPayQRBitmap;
    @SuppressLint("HandlerLeak")
    private Handler SetImageHandler = new Handler(){
        public void handleMessage(Message msg) {
            if (mPayQRIV != null && mPayQRBitmap != null) {
                mPayQRIV.setImageBitmap(mPayQRBitmap);
                CheckOrderStateHandler.sendEmptyMessage(0);
            }
            showProgress(false);
        }
    };

    @SuppressLint("HandlerLeak")
    private Handler CheckOrderStateHandler = new Handler(){
        public void handleMessage(Message msg) {
            checkOrderState();
        }
    };

    @Override
    protected void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_pay);
        setupTitle(getString(R.string.pay));
        initPayMethod();

        mPayQRIV = findViewById(R.id.pay_qr_code);
        mPayNoticeTV = findViewById(R.id.pay_notice);
        mPayNoticeTV.setText(R.string.choose_pay_method);
        mProgressView = findViewById(R.id.progress);

        setupModelObserver();

        parseIntent();
        choosePayMethodOrPay();
    }

    private void initPayMethod() {
        if (mPayMethod.size() == 0) {
            mPayMethod.add(Pay.PAY_TYPE_ALIPAY);
            mPayMethod.add(Pay.PAY_TYPE_WECHAT);
        }
        if (mPayMethodRes.size() == 0) {
            mPayMethodRes.add(R.string.pay_method_alipay);
            mPayMethodRes.add(R.string.pay_method_wechat);
        }
    }

    @Override
    protected void onNewIntent(Intent intent) {
        super.onNewIntent(intent);
        setIntent(intent);
        parseIntent();
        choosePayMethodOrPay();
    }

    private void parseIntent() {
        mCommodityId = getIntent().getIntExtra(INTENT_EXTRA_COMMODITY_ID, -1);
        mChargeAmmount = getIntent().getDoubleExtra(INTENT_EXTRA_CHARGE_AMMOUNT, -1);
        mDepositePlans = getIntent().getIntExtra(INTENT_EXTRA_DEPOSITEPLANS, -1);
        mPriceList = getIntent().getIntegerArrayListExtra(INTENT_EXTRA_PRICE);
        if (mCommodityId < 0 || mDepositePlans < 0 || mChargeAmmount < 0 || mPriceList == null) {
            Log.w(TAG, "INVALID paras");
            showToast(R.string.pay_error);
            finish();
        }
        mPayType = getIntent().getStringExtra(INTENT_EXTRA_PAY_TYPE);
    }

    private void setupModelObserver() {
        mPayViewModel = ViewModelProviders.of(this).get(PayViewModel.class);
        final Observer<RechargeResponse> rechargeResponseObserver = new Observer<RechargeResponse>() {
            @Override
            public void onChanged(@Nullable RechargeResponse response) {
                Log.i(TAG, "onChanged rechargeResponseObserver = " + response);
                if (response != null) {
                    Log.d(TAG, "onChanged code = " + response.getCode()
                            + "; msg = " + response.getMsg());
                    Log.d(TAG, "onChanged data = " + response.getData());
                    if (BaseViewModel.SERVER_RESULT_SUCCESS == response.getCode()) {
                        if (response.getData() != null &&
                                BaseViewModel.PAY_RESULT_SUCCESS == response.getData().getCode()) {
                            mTradeNumber = response.getData().getOut_trade_no();
                            mAppViewModel.getQRCode(response.getData().getQr_code());
                        }
                    } else {
                        showToast(R.string.pay_error);
                        finish();
                    }
                }
            }
        };
        mPayViewModel.rechargeResponseLiveData().observe(this, rechargeResponseObserver);

        final Observer<DefaultResponse> orderResponseObserver = new Observer<DefaultResponse>() {
            @Override
            public void onChanged(@Nullable DefaultResponse response) {
                Log.i(TAG, "onChanged rechargeResponseObserver = " + response);
                if (response != null) {
                    Log.d(TAG, "onChanged code = " + response.getCode()
                            + "; msg = " + response.getMsg());
                    if (BaseViewModel.SERVER_RESULT_PAY_COMPLETE == response.getCode()) {
                        showToast(R.string.pay_success);
                        setResult(Activity.RESULT_OK);
                        finish();
                    } else if (BaseViewModel.SERVER_RESULT_PAY_WAITING == response.getCode()) {
                        CheckOrderStateHandler.sendEmptyMessageDelayed(0, 1000);
                    } else if (BaseViewModel.SERVER_RESULT_PAY_EXPIRED == response.getCode()) {
                        showToast(R.string.pay_expired);
                        finish();
                    } else if (BaseViewModel.SERVER_RESULT_PAY_CANCELLED == response.getCode()) {
                        showToast(R.string.pay_cancelled);
                        finish();
                    } else {
                        showToast(R.string.pay_error);
                        finish();
                    }
                }
            }
        };
        mPayViewModel.orderResponseLiveData().observe(this, orderResponseObserver);

        mAppViewModel = ViewModelProviders.of(this).get(AppViewModel.class);
        final Observer<QRCodeResponse> qrCodeObserver = new Observer<QRCodeResponse>() {
            @Override
            public void onChanged(@Nullable QRCodeResponse response) {
                Log.i(TAG, "onChanged QRCodeResponse = " + response);
                if (response != null) {
                    Log.d(TAG, "onChanged code = " + response.getCode()
                            + "; msg = " + response.getMsg());
                    if (BaseViewModel.SERVER_RESULT_SUCCESS == response.getCode()) {
                        Log.d(TAG, "onChanged qrCodePath = " + response.getQrCode());
                        showPayQRImage(response.getQrCode());
                    }
                }
            }
        };
        mAppViewModel.qrCodeResponse().observe(this, qrCodeObserver);
    }

    private void choosePayMethodOrPay() {
        if (TextUtils.isEmpty(mPayType)) {
            mPayNoticeTV.post(new Runnable() {
                @Override
                public void run() {
                    choosePayMethod();
                }
            });
        } else {
            onPayMethodChosen();
        }
    }

    private void choosePayMethod() {
        LayoutInflater inflater = LayoutInflater.from(getApplicationContext());
        PayMethodAdapter payMethodAdapter = new PayMethodAdapter(inflater);
        if (mListPopupWindow == null) {
            mListPopupWindow = new ListPopupWindow(this);
            mListPopupWindow.setAnchorView(mPayNoticeTV);
            mListPopupWindow.setModal(true);
            mListPopupWindow.setAdapter(payMethodAdapter);
            mListPopupWindow.setOnItemClickListener(new AdapterView.OnItemClickListener() {
                @Override
                public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
                    position = position - mListPopupWindow.getListView().getHeaderViewsCount();
                    if (position < mPayMethod.size()) {
                        mPayType = mPayMethod.get(position);
                        onPayMethodChosen();
                    }
                    mListPopupWindow.dismiss();
                }
            });
            mListPopupWindow.setOnDismissListener(new PopupWindow.OnDismissListener() {
                @Override
                public void onDismiss() {
                    if (mPayType == null) {
                        showToast(R.string.pay_cancelled);
                        finish();
                    }
                }
            });
        }
        mListPopupWindow.show();
    }

    private void onPayMethodChosen() {
        if (Pay.PAY_TYPE_WECHAT.equals(mPayType)) {
            mPayNoticeTV.setText(R.string.pay_by_wechat);
        } else {
            mPayNoticeTV.setText(R.string.pay_by_alipay);
        }
        recharge();
    }

    private void recharge() {
        showProgress(true);
        RechargeRequest rechargeRequest = new RechargeRequest();
        rechargeRequest.setCommodityId(mCommodityId);
        rechargeRequest.setPayType(mPayType);
        rechargeRequest.setChargeAmount(mChargeAmmount);
        rechargeRequest.setDepositPlans(mDepositePlans);
        rechargeRequest.setPrice(mPriceList);
        Random random = new Random();
        rechargeRequest.setRequest_id(random.nextInt(10000)+"");
        Log.d(TAG, "mCommodityId = " + mCommodityId +"; mPayType = " + mPayType
                + "; mChargeAmmount = " + mChargeAmmount + "; mDepositePlans = " + mDepositePlans
                + "; mPriceList = " + mPriceList);
        mPayViewModel.recharge(DuoqinAccount.getAccountToken(this), rechargeRequest);
    }

    private void checkOrderState() {
        mPayViewModel.getOrder(DuoqinAccount.getAccountToken(this), mTradeNumber);
    }

    private void showPayQRImage(final String path) {
        mPayQRBitmap = BitmapFactory.decodeFile(path);
        SetImageHandler.sendEmptyMessage(0);
    }

    private void showProgress(final boolean show) {
        int shortAnimTime = getResources().getInteger(android.R.integer.config_shortAnimTime);
        mProgressView.setVisibility(show ? View.VISIBLE : View.GONE);
        mProgressView.animate().setDuration(shortAnimTime).alpha(
                show ? 1 : 0).setListener(new AnimatorListenerAdapter() {
            @Override
            public void onAnimationEnd(Animator animation) {
                mProgressView.setVisibility(show ? View.VISIBLE : View.GONE);
                mPayQRIV.setVisibility(!show ? View.VISIBLE : View.INVISIBLE);
            }
        });
    }

    private final static class PayMethodAdapter extends BaseAdapter {
        private final LayoutInflater mInflater;

        PayMethodAdapter(LayoutInflater inflater) {
            mInflater = inflater;
        }

        @Override
        public int getCount() {
            return mPayMethod.size();
        }

        @Override
        public Object getItem(int position) {
            return position;
        }

        @Override
        public long getItemId(int position) {
            return position;
        }

        @Override
        public View getView(int position, View convertView, ViewGroup parent) {
            final View resultView =
                    (convertView != null) ? convertView
                            : mInflater.inflate(R.layout.list_item_paymethod, parent, false);
            final TextView payMethodTV = resultView.findViewById(R.id.pay_method);
            payMethodTV.setText(mPayMethodRes.get(position));

            return resultView;
        }
    }

    private void showToast(int resId) {
        Toast toast = Toast.makeText(getApplicationContext(), resId, Toast.LENGTH_SHORT);
        toast.setGravity(Gravity.CENTER, 0, 0);
//        View view = LayoutInflater.from(getApplicationContext()).inflate(R.layout.layout_toast, null);
//        TextView toastTV = view.findViewById(R.id.toast_text);
//        toastTV.setText(resId);
//        toast.setView(view);
        toast.show();
    }
}
